package com.guyu.plugin.satoken.listener;

import cn.dev33.satoken.annotation.handler.SaAnnotationHandlerInterface;
import cn.dev33.satoken.config.SaTokenConfig;
import cn.dev33.satoken.listener.SaTokenListenerForLog;
import cn.dev33.satoken.stp.StpLogic;
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
import cn.hutool.extra.spring.SpringUtil;
import com.guyu.common.web.util.GuyuServletUtils;
import com.guyu.plugin.log.enums.BusinessStatus;
import com.guyu.plugin.log.enums.BusinessType;
import com.guyu.plugin.log.event.LoginLogEvent;
import com.guyu.plugin.satoken.helper.LoginHelper;

import java.util.HashMap;
import java.util.Map;

/**
 * 用户登录登出日志
 */
public class GuyuSaTokenListener extends SaTokenListenerForLog {
    /**
     * 每次登录时触发
     */
    @Override
    public void doLogin(String loginType, Object loginId, String tokenValue, SaLoginParameter loginParameter) {
        super.doLogin(loginType, loginId, tokenValue, loginParameter);
        save(BusinessType.LOGIN, loginType, loginId, tokenValue,
                loginParameter.getDeviceType(), loginParameter.getDeviceId(),
                loginParameter.getTerminalExtraData());
    }

    /**
     * 每次注销时触发
     */
    @Override
    public void doLogout(String loginType, Object loginId, String tokenValue) {
        super.doLogout(loginType, loginId, tokenValue);
        save(BusinessType.LOGOUT, loginType, loginId, tokenValue,
                null, null, null);
    }

    /**
     * 每次被踢下线时触发
     */
    @Override
    public void doKickout(String loginType, Object loginId, String tokenValue) {
        super.doKickout(loginType, loginId, tokenValue);
        save(BusinessType.KICK_OUT, loginType, loginId, tokenValue,
                null, null, null);
    }

    /**
     * 每次被顶下线时触发
     */
    @Override
    public void doReplaced(String loginType, Object loginId, String tokenValue) {
        super.doReplaced(loginType, loginId, tokenValue);
        save(BusinessType.REPLACED, loginType, loginId, tokenValue,
                null, null, null);
    }

    /**
     * 每次被封禁时触发
     */
    @Override
    public void doDisable(String loginType, Object loginId, String service, int level, long disableTime) {
        super.doDisable(loginType, loginId, service, level, disableTime);
        //扩展数据
        Map<String, Object> extraData = new HashMap<>();
        extraData.put("service", service);
        extraData.put("level", level);
        extraData.put("disableTime", disableTime);
        save(BusinessType.DISABLE, loginType, loginId, null,
                null, null, extraData);
    }

    /**
     * 每次被解封时触发
     */
    @Override
    public void doUntieDisable(String loginType, Object loginId, String service) {
        super.doUntieDisable(loginType, loginId, service);
        //扩展数据
        Map<String, Object> extraData = new HashMap<>();
        extraData.put("service", service);
        save(BusinessType.UNTIE_DISABLE, loginType, loginId, null,
                null, null, extraData);
    }

    /**
     * 每次打开二级认证时触发
     */
    @Override
    public void doOpenSafe(String loginType, String tokenValue, String service, long safeTime) {
        super.doOpenSafe(loginType, tokenValue, service, safeTime);
        //登录ID
        Object loginId = LoginHelper.getLoginIdByTokenNotThinkFreeze(loginType, tokenValue);
        //扩展数据
        Map<String, Object> extraData = new HashMap<>();
        extraData.put("service", service);
        extraData.put("isOpen", true);
        save(BusinessType.SECONDARY_CONFIRMATION, loginType, loginId, tokenValue,
                null, null, extraData);
    }

    /**
     * 每次关闭二级认证时触发
     */
    @Override
    public void doCloseSafe(String loginType, String tokenValue, String service) {
        super.doCloseSafe(loginType, tokenValue, service);
        //登录ID
        Object loginId = LoginHelper.getLoginIdByTokenNotThinkFreeze(loginType, tokenValue);
        //扩展数据
        Map<String, Object> extraData = new HashMap<>();
        extraData.put("service", service);
        extraData.put("isOpen", false);
        save(BusinessType.SECONDARY_CONFIRMATION, loginType, loginId, tokenValue,
                null, null, extraData);
    }

    /**
     * 每次创建Session时触发
     */
    @Override
    public void doCreateSession(String id) {
        super.doCreateSession(id);
    }

    /**
     * 每次注销Session时触发
     */
    @Override
    public void doLogoutSession(String id) {
        super.doLogoutSession(id);
    }

    /**
     * 每次Token续期时触发
     */
    @Override
    public void doRenewTimeout(String tokenValue, Object loginId, long timeout) {
        super.doRenewTimeout(tokenValue, loginId, timeout);
    }

    @Override
    public void doRegisterComponent(String compName, Object compObj) {
        super.doRegisterComponent(compName, compObj);
    }

    @Override
    public void doRegisterAnnotationHandler(SaAnnotationHandlerInterface<?> handler) {
        super.doRegisterAnnotationHandler(handler);
    }

    @Override
    public void doSetStpLogic(StpLogic stpLogic) {
        super.doSetStpLogic(stpLogic);
    }

    @Override
    public void doSetConfig(SaTokenConfig config) {
        super.doSetConfig(config);
    }

    /**
     * 记录用户日志
     */
    private void save(BusinessType businessType, String loginType, Object loginId, String tokenValue,
                      String clientType, String clientId, Map<String, Object> extraData) {
        LoginLogEvent loginLog = new LoginLogEvent();
        loginLog.setClientType(clientType);
        loginLog.setClientId(clientId);
        loginLog.setLoginType(loginType);
        loginLog.setLoginId(loginId);
        loginLog.setTokenValue(tokenValue);
        loginLog.setBusinessType(businessType.getCode());
        loginLog.setStatus(BusinessStatus.SUCCESS);
        loginLog.setOpTime(System.currentTimeMillis());
        loginLog.setExtraData(extraData);
        loginLog.setRequest(GuyuServletUtils.getRequest());
        SpringUtil.getApplicationContext().publishEvent(loginLog);
    }
}
